#include "EventDispatcher.h"
#include "EventManager.h"
#include "Events.h"
#include "neiderra/core/Environment.h"
#include "iGraphicsSubsystem.h"
#include "neiderra/core/Core.h"
#include "neiderra/core/iException.h"
#include "neiderra/core/VirtualKeyCodes.h"
#include "neiderra/utils/Logger.h"

using namespace neiderra::gui;
using namespace neiderra::core;

// 
// void sysEventDispatcher::dispatch(aEvent* event)
// {
// 	core->getLogger()->log("Abstract signal recieved");
// }
// 
// void sysEventDispatcher::dispatch(aMouseEvent* event)
// {
// 	//core->getLogger()->log("Mouse event recieved");
//     /*GUIWindow* const win = event->pwin;
//     if(win)
//     {
//         core->getLogger()->log(string(win->getTitle())+" : mouse event");
//         switch(event->type){
//             case mouse_down:
//                 win->onMouseDown(win, 0);
//             break;
//             case mouse_up:
//                 win->onMouseUp(win, 0);
//             break;
//         }
//     }
//     else {
//         core->getLogger()->log("warning! mouse event from undefined sender");
//     }*/
// 
// 	// HACK here
// //	Scene* scene = core->getSceneManager()->GetScene(event->pwin);
// //	sgNode* container = scene->GetIGUIRoot()->FindContainer(event->mx, event->my);
// //	if( container ) {
// //		((IGUIElement*) container)->onMouseClick(container, 0);
// //	}
// 	aScene* scene;
// 	sgNode* reciever;
// 	aCamera* cam;
// 
// 
//     
// 	switch(event->type)
// 	{
// 	case mouse_move:
//         
// 
// 
// 		break;
// 	case mouse_down:
// 		Core::Instance->getLogger()->log("mouse clicked");
// 		break;
// 	case mouse_up:
// 		scene = core->getSceneManager()->GetScene(event->pwin);
// 	
// 		reciever = scene->GetSceneRoot()->GetSGNode()->FindContainer(event->mx, event->my);
// 		if (reciever )
// 		{	
// 			// TODO ��� ��������������� �� ���?
// 			reciever->GetSceneObject()->onMouseDown( reciever  , 0 );
// 		}
// 		break;
// 	}
// }
// 
// void sysEventDispatcher::dispatch(aKeyEvent* event)
// {
// /*	using namespace std;
// 	using namespace rendering;
// 	aScene* scene = core->getSceneManager()->GetScene(event->pwin);
// 	
// 	vec3 dest;
// 	scene->GetCamera()->GetDestination(dest);
// 
// 	vec3 up;
// 	scene->GetCamera()->GetUpVector(up);
// 
// 	vec3 pos;
// 	scene->GetCamera()->GetPosition(pos);
// 	
// 	vec3 rel_dest = dest-pos;
// 	vec3 rel_pos;
// 	
// 	double a = atan((rel_dest.x)/(rel_dest.z));
// 	vec3 delta;
// 	delta.x = 0.2 * sin(a);
// 	delta.z = 0.2 * cos(a);
// 	delta.y = 0;
// */
// 
// 	aCamera* cam = core->getSceneManager()->GetScene(event->pwin)->GetCamera();
// 	aScene* scene;
// 	switch(event->keycode)
// 	{
// 	case vk_left:
// 
// 		cam->RotateLeft(0.2);
// 
// 		break;
// 	case vk_right:
// 
// 		cam->RotateRight(0.2);
// 
// 		break;
// 	case vk_up:
// 
// 		cam->MoveForward(0.3);
// 
// 		break;
// 	case vk_down:
// 
// 		cam->MoveBackward(0.3);
// 		
// 		break;
// 	case vk_esc:
// 		core->shutdown();
// 		break;
// 
// 	case vk_numpad7:
// 		cam->MoveUp(0.3);
// 		break;
// 
// 	case vk_numpad9:
// 		cam->MoveDown(0.3);
// 		break;
// 
// 	case vk_numpad8:
// 		cam->RollDown(-0.3);
// 		break;
// 
// 	case vk_numpad5:
// 		cam->RollDown(0.3);
// 		break;
// 
// 	case vk_numpad4:
// 		cam->MoveLeft(0.2);
// 		break;
// 
// 	case vk_numpad6:
// 		cam->MoveRight(0.2);
// 		break;
// 
// 	case vk_f5:
// 		scene = core->getSceneManager()->GetDefaultScene();
// 		scene->cleanUp();
// 		scene->reload();
// 		core->getGraphicsSubSystem()->getRenderer()->SetSceneRoot(scene->GetSceneRoot()->GetSGNode());
// 		break;
// 	}
// 
// 	//core->getLogger()->log("Key event recieved");
// }
// 
// void sysEventDispatcher::dispatch(aSysEvent* event)
// {
// }
// 
// using neiderra::core::events::aSceneEvent;
// void sysEventDispatcher::dispatch(aSceneEvent* event)
// {
// 	event->_handler(event->_sender, event->_args);
// }
// 
// /*void sysEventDispatcher::dispatch(InternalEvent* e)
// {
// 	if(!e) return;
// 	switch(e->source)
// 	{
// 	case INTEventSource::Mouse: 
// 		break;
// 	case INTEventSource::Keyboard:
// 		break;
// 	case INTEventSource::GUI:
// 		break;
// 	case INTEventSource::Scene:
// 		break;
// 	case INTEventSource::System:
// 		break;
// 	}
// }*/
// 
// void sysEventDispatcher::dispatch(sysShutDownEvent* event)
// {
// 	core->getLogger()->log("Shutdown signal recieved");
// 	core->shutdown();
// }
// 

EventDispatcher::EventDispatcher(Core* core): Base(core)
{
}

EventDispatcher::~EventDispatcher()
{
}

void EventDispatcher::dispatch(GUIMouseEvent* event)
{
	switch(event->type)
	{
	case GUIMouseEvent::mouse_click:

		// fixme: mouse click doesn't work, down & up instead
		core->getLogger()->log("mouse click");

		break;

	case GUIMouseEvent::mouse_down:

		core->getLogger()->log("mouse down");

		break;

	case GUIMouseEvent::mouse_up:

		core->getLogger()->log("mouse up");

		break;

	case GUIMouseEvent::mouse_move:
		break;
		
	default:
		throw ENotImplemented("mouse event type");
	}
}

void EventDispatcher::dispatch(GUIKeyEvent* event)
{
	switch(event->keycode)
	{
		case vk_esc:
			core->getEnvironment()->executeMethod("shutdown");
			break;
	}
	core->getLogger()->log("key pressed");
}

void EventDispatcher::dispatchEvents()
{
	EventManager* manager = core->getGraphicsSubsystem()->getEventManager();
	
	iGUIEvent* event=0;
	
	do
	{
		event = manager->nextEvent();
		if(event)
			event->response(this);
		
		delete event;
	}
	while(event!=0);
}
// 
